package com.xiaowen.config.filter;

import com.xiaowen.config.security.SmsCodeAuthenticationToken;
import com.xiaowen.tool.JsonUtils;
import com.xiaowen.tool.jwt.CheckResult;
import com.xiaowen.tool.jwt.JWTConstant;
import com.xiaowen.tool.jwt.JWTUtil;
import com.xiaowen.user.entity.User;
import com.xiaowen.user.service.UserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: yf-wenhao
 * Date: 2024/9/18
 * Time: 下午10:09
 */
@Slf4j
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager,UserService userService) {
        super(authenticationManager);
        this.userService = userService;
    }

    private UserService userService;


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain)
            throws IOException, ServletException {

        String token = request.getHeader("token");
        log.info("token--------{}",token);
        if (Arrays.asList("/login", "/login/authCode", "/favicon.ico").contains(request.getRequestURI())) {
            chain.doFilter(request, response);
            return;
        }
        // 验证Token，如果验证失败对失败进行处理
        CheckResult checkResult = JWTUtil.validateJWT(token);
        if(!checkResult.isSuccess()){
            switch(checkResult.getErrCode()){
                case JWTConstant.JWT_ERRCODE_NULL: throw new JwtException("Token 不存在");
                case JWTConstant.JWT_ERRCODE_EXPIRE: throw new JwtException("Token 已过期");
                case JWTConstant.JWT_ERRCODE_FAIL: throw new JwtException("Token 认证过期");
            }
        }
        // 解析jwt去获取用户名
        Claims claims = checkResult.getClaims();
        String phone = claims.getSubject();
        User sysUser = userService.findByPhone(phone);
        // 根据查询的用户信息封装成一个Authentication用户认证信息
        SmsCodeAuthenticationToken auth = new SmsCodeAuthenticationToken(sysUser,null,null);
        // 将得到的用户认证信息填入到上下文中
        SecurityContextHolder.getContext().setAuthentication(auth);
        logParam(request);
        // 放行
        chain.doFilter(request,response);
    }


    private void logParam(HttpServletRequest request){
        Map<String, Object> requestBody = new HashMap<>();
        // 打印所有请求参数
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            requestBody.put(paramName, paramValue);
        }
        log.info("requestUri:{}",request.getRequestURI());
        log.info("requestBody:{}", JsonUtils.toJson(requestBody));
    }


    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
